{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "\n",
    "mnist_train = pd.read_csv('../data/mnist_train.csv',header=None)\n",
    "mnist_test = pd.read_csv('../data/mnist_test.csv',header=None)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "X_train: (60000, 784)\n",
      "y_train: (60000,)\n",
      "X_test: (10000, 784)\n",
      "y_test: (10000,)\n"
     ]
    }
   ],
   "source": [
    "mnist_train.head()\n",
    "X_train=mnist_train.loc[:,1:].values\n",
    "y_train=mnist_train.loc[:,0].values\n",
    "X_test=mnist_test.loc[:,1:].values\n",
    "y_test=mnist_test.loc[:,0].values\n",
    "\n",
    "X_train=X_train/255.\n",
    "X_test=X_test/255.\n",
    "\n",
    "print('X_train:',X_train.shape)\n",
    "print('y_train:',y_train.shape)\n",
    "print('X_test:',X_test.shape)\n",
    "print('y_test:',y_test.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/anaconda3/lib/python3.6/importlib/_bootstrap.py:219: RuntimeWarning: compiletime version 3.5 of module 'tensorflow.python.framework.fast_tensor_util' does not match runtime version 3.6\n",
      "  return f(*args, **kwds)\n"
     ]
    }
   ],
   "source": [
    "import tensorflow as tf\n",
    "sess = tf.InteractiveSession()\n",
    "\n",
    "inputs = tf.placeholder(tf.float32, [None, 784])\n",
    "inputs_reshaped = tf.reshape(inputs, (-1,28,28,1))\n",
    "y = tf.placeholder(tf.int64, [None, 1])\n",
    "y_onehot = tf.one_hot(y, 10)\n",
    "n_class=10\n",
    "n_feature=512\n",
    "# 构建中心\n",
    "with tf.variable_scope('center'):\n",
    "    centers = tf.get_variable('centers', [n_class, n_feature], dtype=tf.float32,\\\n",
    "                              initializer=tf.constant_initializer(0), trainable=False)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# 定义模型，复杂loss\n",
    "from tensorflow.contrib.keras import layers\n",
    "\n",
    "def VGG6(inputs, n_class=10, return_feature=False):\n",
    "    # Block 1\n",
    "    x = layers.Conv2D(32, (3, 3), activation='relu', padding='same', name='block1_conv1')(inputs)\n",
    "    x = layers.Conv2D(32, (3, 3), activation='relu', padding='same', name='block1_conv2')(x)\n",
    "    x = layers.MaxPooling2D((2, 2), strides=(2, 2), name='block1_pool')(x)\n",
    "\n",
    "    # Block 2\n",
    "    x = layers.Conv2D(64, (3, 3), activation='relu', padding='same', name='block2_conv1')(x)\n",
    "    x = layers.Conv2D(64, (3, 3), activation='relu', padding='same', name='block2_conv2')(x)\n",
    "    x = layers.MaxPooling2D((2, 2), strides=(2, 2), name='block2_pool')(x)\n",
    "\n",
    "    x = layers.Flatten(name='flatten')(x)\n",
    "    x = layers.Dense(512, activation='relu', name='fc1')(x)\n",
    "    features = layers.Dense(512, activation='relu', name='fc2')(x)\n",
    "    outputs = layers.Dense(n_class, activation='softmax', name='predictions')(features)\n",
    "    \n",
    "    if return_feature:\n",
    "        return outputs, features\n",
    "    else:\n",
    "        return outputs\n",
    "    \n",
    "def center_loss(features, label, alpha, nrof_classes):\n",
    "    \"\"\"Center loss based on the paper \"A Discriminative Feature Learning Approach for Deep Face Recognition\"\n",
    "       (http://ydwen.github.io/papers/WenECCV16.pdf)\n",
    "    \"\"\"\n",
    "    # 生成可以共享的变量centers\n",
    "    with tf.variable_scope('center', reuse=True):\n",
    "        centers = tf.get_variable('centers')\n",
    "    label = tf.reshape(label, [-1])\n",
    "\n",
    "    # 取出对应label下对应的center值，注意label里面的值可能会重复，因为一个标签下有可能会出现多个人\n",
    "    centers_batch = tf.gather(centers, label)\n",
    "\n",
    "    # 求特征点到中心的距离并乘以一定的系数，alfa是center的更新速度，越大代表更新的越慢\n",
    "    diff = centers_batch - features\n",
    "\n",
    "    # 获取一个batch中同一样本出现的次数，这里需要理解论文中的更新公式\n",
    "    unique_label, unique_idx, unique_count = tf.unique_with_counts(label)\n",
    "    appear_times = tf.gather(unique_count, unique_idx)\n",
    "    appear_times = tf.reshape(appear_times, [-1, 1])\n",
    "\n",
    "    diff = diff / tf.cast((1 + appear_times), tf.float32)\n",
    "    diff = alpha * diff\n",
    "\n",
    "    # 更新center，输出是将对应于label的centers减去对应的diff，如果同一个标签出现多次，那么就减去多次\n",
    "    centers = tf.scatter_sub(centers, label, diff)\n",
    "\n",
    "    # 求center loss，这里是将l2_loss里面的值进行平方相加，再除以2，并没有进行开方\n",
    "    loss = tf.nn.l2_loss(features - centers_batch)\n",
    "    \n",
    "    return loss, centers\n",
    "\n",
    "def island_loss(features, label, alpha, nrof_classes, nrof_features, lamda1=10):\n",
    "    \"\"\"Center loss based on the paper \"Island Loss for Learning Discriminative Features in Facial Expression Recognition\"\n",
    "       (https://github.com/SeriaZheng/EmoNet/blob/master/loss_function/loss_paper/Island_loss.pdf)\n",
    "    \"\"\"\n",
    "    # 生成可以共享的变量centers\n",
    "    with tf.variable_scope('center', reuse=True):\n",
    "        centers = tf.get_variable('centers')\n",
    "    label = tf.reshape(label, [-1])\n",
    "\n",
    "    # 取出对应label下对应的center值，注意label里面的值可能会重复，因为一个标签下有可能会出现多个人\n",
    "    centers_batch = tf.gather(centers, label)\n",
    "\n",
    "    # 求特征点到中心的距离并乘以一定的系数，diff1为center loss\n",
    "    diff1 = centers_batch - features\n",
    "\n",
    "    # 获取一个batch中同一样本出现的次数，这里需要理解论文中的更新公式\n",
    "    unique_label, unique_idx, unique_count = tf.unique_with_counts(label)\n",
    "    appear_times = tf.gather(unique_count, unique_idx)\n",
    "    appear_times = tf.reshape(appear_times, [-1, 1])\n",
    "\n",
    "    diff1 = diff1 / tf.cast((1 + appear_times), tf.float32)\n",
    "    diff1 = alpha * diff1\n",
    "\n",
    "    # diff2为island loss的center更新项\n",
    "    diff2 = tf.get_variable('diff2', [nrof_classes, nrof_features], dtype=tf.float32,\\\n",
    "                              initializer=tf.constant_initializer(0), trainable=False)\n",
    "    for i in range(nrof_classes):\n",
    "        for j in range(nrof_classes):\n",
    "            if i!=j:\n",
    "                diff2 = tf.scatter_add(diff2, i,\n",
    "                                       (tf.gather(centers, i) / tf.sqrt(\n",
    "                                           tf.reduce_sum(tf.square(tf.gather(centers, i)))) * tf.sqrt(\n",
    "                                           tf.reduce_sum(tf.square(tf.gather(centers, j)))))\n",
    "                                       - tf.multiply(\n",
    "                                           (tf.reduce_sum(\n",
    "                                               tf.multiply(tf.gather(centers, i), tf.gather(centers, j))) / tf.sqrt(\n",
    "                                               tf.reduce_sum(tf.square(tf.gather(centers, i)))) *\n",
    "                                            tf.pow(tf.sqrt(tf.reduce_sum(tf.square(tf.gather(centers, j)))), 3)),\n",
    "                                           tf.gather(centers, j)))\n",
    "    diff2 = diff2 * lamda1 / (nrof_classes - 1)\n",
    "    diff2 = alpha * diff2\n",
    "\n",
    "    # 求center loss，这里是将l2_loss里面的值进行平方相加，再除以2，并没有进行开方\n",
    "    loss1 = tf.nn.l2_loss(features - centers_batch)\n",
    "\n",
    "    # 求island loss\n",
    "    loss2 = tf.zeros(1)\n",
    "    for i in range(nrof_classes):\n",
    "        for j in range(nrof_classes):\n",
    "            if i!=j:\n",
    "                loss2 = tf.add(tf.add(tf.reduce_sum(tf.multiply(tf.gather(centers, i), tf.gather(centers, j))) / (\n",
    "                        tf.sqrt(tf.reduce_sum(tf.square(tf.gather(centers, i)))) *\n",
    "                        tf.sqrt(tf.reduce_sum(tf.square(tf.gather(centers, j))))), tf.ones(1)), loss2)\n",
    "    loss2 = lamda1 * loss2\n",
    "\n",
    "    loss = tf.add(loss1,loss2)\n",
    "\n",
    "    # 更新center，输出是将对应于label的centers减去对应的diff，如果同一个标签出现多次，那么就减去多次(diff1与centers维度不同)\n",
    "    centers = tf.scatter_sub(centers, label, diff1)\n",
    "    # diff2维度与centers相同可以直接减\n",
    "    centers = tf.subtract(centers, diff2)\n",
    "\n",
    "    return loss, centers"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[epoch:1/6, steps:468/468] -loss: nan - acc: 65.68%  [validate:78/78] -loss: 14.3967 - acc: 81.41%      \n",
      "\n",
      "[epoch:2/6, steps:468/468] -loss: 14.0710 - acc: 94.61%  [validate:78/78] -loss: 13.8294 - acc: 98.86%      \n",
      "\n",
      "[epoch:3/6, steps:468/468] -loss: 13.7889 - acc: 98.89%  [validate:78/78] -loss: 13.7253 - acc: 99.11%      \n",
      "\n",
      "[epoch:4/6, steps:468/468] -loss: 13.7089 - acc: 99.17%  [validate:78/78] -loss: 13.6985 - acc: 99.22%      \n",
      "\n",
      "[epoch:5/6, steps:468/468] -loss: 13.6642 - acc: 99.32%  [validate:78/78] -loss: 13.6272 - acc: 99.31%      \n",
      "\n",
      "[epoch:6/6, steps:468/468] -loss: 13.6316 - acc: 99.43%  [validate:78/78] -loss: 13.6182 - acc: 99.29%      \n",
      "\n"
     ]
    }
   ],
   "source": [
    "# training graph\n",
    "import numpy as np\n",
    "# cal loss\n",
    "preds,features = VGG6(inputs_reshaped, return_feature=True)\n",
    "softmax_loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=preds, labels=y_onehot))\n",
    "island_loss, update_centers = island_loss(features, y, 0.5, n_class, n_feature)\n",
    "loss = tf.reduce_mean(softmax_loss + 0.01 * island_loss)\n",
    "\n",
    "# cal acc\n",
    "result = tf.argmax(preds,1)\n",
    "ground_truth = tf.reshape(y, [-1])\n",
    "correct_prediction = tf.equal(result, ground_truth)\n",
    "accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))\n",
    "\n",
    "# train\n",
    "train_step = tf.train.AdamOptimizer(1e-4).minimize(loss)\n",
    "\n",
    "n_epochs=6\n",
    "batch_size=128\n",
    "n_batch = int(X_train.shape[0] / batch_size)\n",
    "n_batch_val = int(X_test.shape[0] / batch_size)\n",
    "sess.run(tf.global_variables_initializer())\n",
    "for epoch in range(n_epochs):\n",
    "    # training step\n",
    "    index=np.arange(X_train.shape[0])\n",
    "    np.random.shuffle(index)\n",
    "    X_train=X_train[index,:]\n",
    "    y_train=y_train[index]\n",
    "    sum_loss=0\n",
    "    sum_acc=0\n",
    "    last_train_str=\"\"\n",
    "    for i in range(n_batch):\n",
    "        x_temp=X_train[i*batch_size:(i+1)*batch_size,:]\n",
    "        y_temp=y_train[i*batch_size:(i+1)*batch_size]\n",
    "        y_temp=np.reshape(y_temp,(batch_size,1))\n",
    "        feed_dict = {inputs: x_temp, y: y_temp}\n",
    "        _,_,loss_value,acc_value=sess.run([train_step, update_centers, loss, accuracy], feed_dict=feed_dict)\n",
    "        sum_loss+=loss_value\n",
    "        sum_acc+=(acc_value*100)\n",
    "        last_train_str = \"\\r[epoch:%d/%d, steps:%d/%d] -loss: %.4f - acc: %.2f%%\" % \\\n",
    "              (epoch+1, n_epochs, i+1, n_batch, sum_loss/(i+1), sum_acc/(i+1))\n",
    "        print(last_train_str, end='      ', flush=True)\n",
    "    \n",
    "    # validating step\n",
    "    sum_loss=0\n",
    "    sum_acc=0\n",
    "    for i in range(n_batch_val):\n",
    "        x_temp=X_test[i*batch_size:(i+1)*batch_size,:]\n",
    "        y_temp=y_test[i*batch_size:(i+1)*batch_size]\n",
    "        y_temp=np.reshape(y_temp,(batch_size,1))\n",
    "        feed_dict = {inputs: x_temp, y: y_temp}\n",
    "        loss_value,acc_value=sess.run([loss, accuracy], feed_dict=feed_dict)\n",
    "        sum_loss+=loss_value\n",
    "        sum_acc+=(acc_value*100)\n",
    "        print(last_train_str+\"  [validate:%d/%d] -loss: %.4f - acc: %.2f%%\" % \\\n",
    "              (i+1, n_batch_val, sum_loss/(i+1), sum_acc/(i+1)), end='      ', flush=True)\n",
    "    print('\\n')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[feature extracting:5/5]      (640, 512)\n",
      "(640, 2)\n"
     ]
    },
    {
     "data": {
      "image/png": "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\nyNMHAAAAAElFTkSuQmCC\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x13e6e9c88>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# crossentropy_loss 获取倒数第二层的特征 98.47%\n",
    "index=np.arange(X_train.shape[0])\n",
    "X_draw=X_train[index[0:640],:]\n",
    "y_draw=y_train[index[0:640]]\n",
    "mid_features=[]\n",
    "n_batch=int(640/batch_size)\n",
    "for i in range(n_batch):\n",
    "    x_temp=X_draw[i*batch_size:(i+1)*batch_size,:]\n",
    "    mid_feature_temp=sess.run([features], feed_dict={inputs:x_temp})\n",
    "    mid_features.append(mid_feature_temp[0])\n",
    "    print(\"\\r[feature extracting:%d/%d]\" % (i+1, n_batch), end='      ', flush=True)\n",
    "mid_features=np.concatenate(mid_features, axis=0)\n",
    "print(mid_features.shape)\n",
    "\n",
    "#crossentropy_loss\n",
    "from sklearn.manifold import TSNE\n",
    "tsne=TSNE(n_components=2)\n",
    "mid_features=tsne.fit_transform(mid_features)  #进行数据降维,降成两维\n",
    "print(mid_features.shape)\n",
    "from matplotlib import pyplot as plt\n",
    "plt.scatter(x=mid_features[:,0],y=mid_features[:,1],c=y_draw)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[feature extracting:5/5]      (640, 512)\n",
      "(640, 2)\n"
     ]
    },
    {
     "data": {
      "image/png": "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\nhvh/5vMkdPb3a/0AAAAASUVORK5CYII=\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x13fc4cd68>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# center_loss 获取倒数第二层的特征 99.30%\n",
    "index=np.arange(X_train.shape[0])\n",
    "X_draw=X_train[index[0:640],:]\n",
    "y_draw=y_train[index[0:640]]\n",
    "mid_features=[]\n",
    "n_batch=int(640/batch_size)\n",
    "for i in range(n_batch):\n",
    "    x_temp=X_draw[i*batch_size:(i+1)*batch_size,:]\n",
    "    mid_feature_temp=sess.run([features], feed_dict={inputs:x_temp})\n",
    "    mid_features.append(mid_feature_temp[0])\n",
    "    print(\"\\r[feature extracting:%d/%d]\" % (i+1, n_batch), end='      ', flush=True)\n",
    "mid_features=np.concatenate(mid_features, axis=0)\n",
    "print(mid_features.shape)\n",
    "\n",
    "#crossentropy_loss\n",
    "from sklearn.manifold import TSNE\n",
    "tsne=TSNE(n_components=2)\n",
    "mid_features=tsne.fit_transform(mid_features)  #进行数据降维,降成两维\n",
    "print(mid_features.shape)\n",
    "from matplotlib import pyplot as plt\n",
    "plt.scatter(x=mid_features[:,0],y=mid_features[:,1],c=y_draw)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[feature extracting:5/5]      (640, 512)\n",
      "(640, 2)\n"
     ]
    },
    {
     "data": {
      "image/png": "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\nAElFTkSuQmCC\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x1432ab160>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# island_loss 获取倒数第二层的特征 99.29%\n",
    "index=np.arange(X_train.shape[0])\n",
    "X_draw=X_train[index[0:640],:]\n",
    "y_draw=y_train[index[0:640]]\n",
    "mid_features=[]\n",
    "n_batch=int(640/batch_size)\n",
    "for i in range(n_batch):\n",
    "    x_temp=X_draw[i*batch_size:(i+1)*batch_size,:]\n",
    "    mid_feature_temp=sess.run([features], feed_dict={inputs:x_temp})\n",
    "    mid_features.append(mid_feature_temp[0])\n",
    "    print(\"\\r[feature extracting:%d/%d]\" % (i+1, n_batch), end='      ', flush=True)\n",
    "mid_features=np.concatenate(mid_features, axis=0)\n",
    "print(mid_features.shape)\n",
    "\n",
    "#crossentropy_loss\n",
    "from sklearn.manifold import TSNE\n",
    "tsne=TSNE(n_components=2)\n",
    "mid_features=tsne.fit_transform(mid_features)  #进行数据降维,降成两维\n",
    "print(mid_features.shape)\n",
    "from matplotlib import pyplot as plt\n",
    "plt.scatter(x=mid_features[:,0],y=mid_features[:,1],c=y_draw)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
